package net.xiaosaguo.mymall.auth.controller;

import com.alibaba.fastjson.TypeReference;
import net.xiaosaguo.common.constant.AuthConstant;
import net.xiaosaguo.common.exception.BizCodeEnum;
import net.xiaosaguo.common.pojo.vo.MemberVO;
import net.xiaosaguo.common.utils.R;
import net.xiaosaguo.mymall.auth.feign.MemberFeignService;
import net.xiaosaguo.mymall.auth.feign.ThirdPartyFeignService;
import net.xiaosaguo.mymall.auth.vo.UserLoginVO;
import net.xiaosaguo.mymall.auth.vo.UserRegisterVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import javax.servlet.http.HttpSession;
import javax.validation.Valid;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * description: 登录 controller
 *
 * @author xiaosaguo
 * @date 2020/07/04
 */
@Controller
public class LoginController {

    /*
     * 发送一个请求直接跳转到一个页面
     * Spring MVC ViewController；将请求和页面映射过来
     */
    // @GetMapping({"/register.html"})
    // public String register() {
    //     return "register";
    // }

    @GetMapping({"/login.html", "/index.html", "/"})
    public String login(HttpSession session) {
        Object attribute = session.getAttribute(AuthConstant.LOGIN_USER);
        if (attribute != null) {
            return "redirect:http://mymall.com";
        }
        return "login";
    }


    @Autowired
    ThirdPartyFeignService thirdPartyFeignService;

    @Autowired
    MemberFeignService memberFeignService;

    @Autowired
    StringRedisTemplate redis;

    @GetMapping("/sms/sendCode")
    @ResponseBody
    public R sendCode(@RequestParam String phone) {

        // todo 1. 接口防刷

        // 防止同一个 phone 在 60s 内再次发送验证码
        String codeCache = redis.opsForValue().get(AuthConstant.SMS_CODE_CACHE_PREFIX + phone);
        if (codeCache != null) {
            long l = Long.parseLong(codeCache.split("_")[1]);
            if (System.currentTimeMillis() - l < 60000) {
                return R.error(BizCodeEnum.SMS_CODE_EXCEPTION.getCode(), BizCodeEnum.SMS_CODE_EXCEPTION.getMessage());
            }
        }

        String code = UUID.randomUUID().toString().substring(0, 5);
        String codeRedis = code + "_" + System.currentTimeMillis();
        System.out.println(codeRedis);

        // 2. 验证码的再次校验 redis  key-phone,value-code
        redis.opsForValue().set(AuthConstant.SMS_CODE_CACHE_PREFIX + phone, codeRedis, 10, TimeUnit.MINUTES);

        // FIXME 上线时需要打开
        // thirdPartyFeignService.sendCode(phone, code);
        return R.ok();
    }

    @PostMapping("/register")
    public String register(@Valid UserRegisterVO user, BindingResult result, RedirectAttributes attributes) {
        if (result.hasErrors()) {
            // result.getFieldErrors().stream()
            //         .map(fieldError -> errors.put(fieldError.getField(), fieldError.getDefaultMessage()))
            //         .collect(Collectors.toList());
            Map<String, String> errors = result.getFieldErrors().stream()
                    .collect(Collectors.toMap(FieldError::getField, FieldError::getDefaultMessage));

            // model.addAttribute("errors", errors);

            // type=Method Not Allowed, status=405
            // 用户注册-->/register[post]-->转发/register.html（默认路径都是get方法）
            // 转发：原请求原封不动转给下一个人
            // 校验出错，转发到注册页面
            // return "forward:/register.html";

            // 防止表单重复提交
            attributes.addFlashAttribute("errors", errors);
            /*
             * 重定向携带数据，利用session原理，将数据放在session中，重定向到页面后再从页面中取出来，取出来后就会删除
             * RedirectAttributes 的实现原理是 session。
             * addFlashAttribute 取一次后就删除
             * TODO 分布式 session
             */

            return "redirect:http://auth.mymall.com/register.html";
        }

        // 校验验证码
        String code = user.getCode();
        String codeCache = redis.opsForValue().get(AuthConstant.SMS_CODE_CACHE_PREFIX + user.getPhone());
        if (codeCache != null && code.equals(codeCache.split("_")[0])) {
            // 删除验证码
            redis.delete(AuthConstant.SMS_CODE_CACHE_PREFIX + user.getPhone());
            // 参数校验成功，进行注册逻辑,调用远程服务
            R r = memberFeignService.register(user);
            if (r.getCode() == 0) {
                return "redirect:http://auth.mymall.com/login.html";
            } else {
                Map<String, String> errors = new HashMap<>(1);
                errors.put("msg", r.get("msg").toString());
                attributes.addFlashAttribute("errors", errors);
                return "redirect:http://auth.mymall.com/register.html";
            }
        } else {
            Map<String, String> errors = new HashMap<>(1);
            errors.put("code", "验证码错误");
            attributes.addFlashAttribute("errors", errors);
            return "redirect:http://auth.mymall.com/register.html";
        }
        // 注册成功，回到登录页
        // return "redirect:/login.html";
    }

    @PostMapping("/login")
    public String login(UserLoginVO vo, RedirectAttributes attributes, HttpSession session) {

        // 远程登录
        R r = memberFeignService.login(vo);
        if (r.getCode() == 0) {
            // 成功
            MemberVO member = r.getData(new TypeReference<>() {
            });
            session.setAttribute(AuthConstant.LOGIN_USER, member);
            return "redirect:http://mymall.com";
        } else {
            Map<String, String> errors = new HashMap<>(8);
            errors.put("msg", r.get("msg").toString());
            attributes.addFlashAttribute("errors", errors);
            return "redirect:http://auth.mymall.com/login.html";
        }
    }
}
